package com.hhkj.api.withdrawal.service.biz.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.github.pagehelper.PageInfo;
import com.hhkj.admin.sale.common.cont.SaleWithdrawalConst;
import com.hhkj.admin.sale.common.cont.withdrawal.WithdrawalStatusEnum;
import com.hhkj.admin.sale.domain.Sale;
import com.hhkj.admin.sale.domain.SaleAccount;
import com.hhkj.admin.sale.domain.SaleWithdrawalAccount;
import com.hhkj.admin.sale.model.dopo.SaleWithdrawalDo;
import com.hhkj.admin.sale.model.dopo.SaleWithdrawalPo;
import com.hhkj.admin.sale.service.base.SaleAccountService;
import com.hhkj.admin.sale.service.base.SaleService;
import com.hhkj.admin.sale.service.base.SaleWithdrawalAccountService;
import com.hhkj.admin.sale.service.base.SaleWithdrawalService;
import com.hhkj.admin.sale.service.extend.SaleWithdrawalExtendService;
import com.hhkj.api.common.service.biz.base.SalePasswordService;
import com.hhkj.api.sale.common.component.manager.ApiSaleLoginManager;
import com.hhkj.api.sale.common.session.holder.ApiSaleSessionHolder;
import com.hhkj.api.withdrawal.model.req.ApiWithdrawalCurrentDayCountRes;
import com.hhkj.api.withdrawal.model.req.ApiWithdrawalPagingReq;
import com.hhkj.api.withdrawal.model.req.ApiWithdrawalSaveReq;
import com.hhkj.api.withdrawal.model.res.ApiWithdrawalDetailRes;
import com.hhkj.api.withdrawal.model.res.ApiWithdrawalPagingRes;
import com.hhkj.api.withdrawal.service.biz.ApiSaleWithdrawalBizService;
import com.hhkj.payment.alipay.AliPayApi;
import com.ruoyi.common.cont.SysConst;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.utils.paging.PageInfoUtils;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

/**
 * ApiSaleWithdrawalBizServiceImpl
 *
 * @author zheng
 * @since 2023/11/7 0:47
 */
@Slf4j
@Service
public class ApiSaleWithdrawalBizServiceImpl implements ApiSaleWithdrawalBizService {

    @Autowired
    private SaleWithdrawalService withdrawalService;
    @Autowired
    private SaleWithdrawalExtendService withdrawalExtendService;
    @Autowired
    private SaleService saleService;
    @Autowired
    private SaleAccountService saleAccountService;
    @Autowired
    private SaleWithdrawalAccountService saleWithdrawalAccountService;
    @Resource(name = "salePasswordService")
    private SalePasswordService salePasswordService;
    @Autowired
    private ApiSaleLoginManager loginManager;

    /** 日提现次数 */
    private static final Integer DAY_WITHDRAWAL_LIMIT_AMOUNT = 1;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public synchronized boolean save(ApiWithdrawalSaveReq req) {
        // 校验体现数额是否为100的倍数
        if (req.getPrice().remainder(new BigDecimal(100)).compareTo(BigDecimal.ZERO) != 0) {
            throw new GlobalException("提现金额只允许100的倍数");
        }
        // 校验密码信息
        Long saleId = ApiSaleSessionHolder.getSaleId();
        Sale salePo = saleService.getById(saleId);
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(salePo.getMobile(), req.getPassword());
        AuthenticationContextHolder.setContext(authenticationToken);
        salePasswordService.validate(salePo.getPassword(), MAX_RETRY_COUNT, LOCK_TIME, TIME_UNIT, ACCOUNT_LOCK_TYPE);
        // 获取rootSale信息
        Sale saleRootPo = saleService.getById(salePo.getRootId());
        // 校验今日提现次数
        ApiWithdrawalCurrentDayCountRes countAmountCurrentDay = this.countAmountCurrentDay();
        if (countAmountCurrentDay.getUsedTimes() >= countAmountCurrentDay.getTotalTimes()) {
            throw new GlobalException("今日提现次数已达上限，请于明日重试");
        }
        // 查看退款账户是否存在
        SaleWithdrawalAccount withdrawalAccountPo = saleWithdrawalAccountService.getById(req.getAccountId());
        if (ObjectUtil.isNull(withdrawalAccountPo)) {
            throw new GlobalException("提现账户信息不存在");
        }
        // 校验用户余额
        SaleAccount accountPo = saleAccountService.getBySaleId(saleId);
        if (accountPo.getBalancePrice().compareTo(req.getPrice()) < 1) {
            throw new GlobalException("账户余额不足");
        }
        // 创建提现信息
        req.setAccount(withdrawalAccountPo.getAccount());
        req.setAccountName(withdrawalAccountPo.getName());
        req.setAccountTypeCode(withdrawalAccountPo.getTypeCode());
        // 销售信息
        req.setSaleId(saleId);
        req.setSaleNum(salePo.getNum());
        req.setSaleName(salePo.getName());
        req.setSaleRootId(salePo.getRootId());
        req.setSaleRootNum(saleRootPo.getNum());
        req.setSaleRootName(saleRootPo.getName());
        // 创建提现信息
        boolean saveResult = withdrawalExtendService.save(req);
        if (!saveResult) {
            return false;
        }
        // 修改账户信息 余额减掉， 提现中金额加对应数据
        accountPo.setBalancePrice(accountPo.getBalancePrice().subtract(req.getPrice()));
        // 请求阿里云提现功能接口
        AlipayFundTransUniTransferResponse transferResponse = AliPayApi.fundTransUniTransfer(req.getNum(), req.getRemark(),
                withdrawalAccountPo.getAccount(), withdrawalAccountPo.getName(),
                String.valueOf(req.getPrice().setScale(2, RoundingMode.DOWN)), req.getNum());
        // 退款失败 修改订单信息 修改
        if (!transferResponse.isSuccess()) {
            // req.setFailDescription(transferResponse.);
            // withdrawalService.updateById(req);
            throw new GlobalException(transferResponse.getSubMsg());
        }
        // 计算累计提现金额
        BigDecimal accumulatePrice = withdrawalService.countAccumulatePriceBySaleId(saleId);
        accumulatePrice = accumulatePrice.add(req.getPrice());
        req.setAccumulatePrice(accumulatePrice);
        req.setCompleteFlag(SysConst.Flag.IS.getFlag());
        req.setStatusCode(WithdrawalStatusEnum.NORMAL.getCode());
        // req.setStatusCode(WithdrawalStatusEnum.EXCEPTION.getCode());
        req.setAlipayNum(transferResponse.getPayFundOrderId());
        req.setCompleteTime(DateUtil.parse(transferResponse.getTransDate()));
        withdrawalService.updateById(req);
        // 更新数据
        return saleAccountService.updateById(accountPo);
    }

    @Override
    public ApiWithdrawalCurrentDayCountRes countAmountCurrentDay() {
        Long saleId = ApiSaleSessionHolder.getSaleId();
        SaleWithdrawalDo withdrawalDo = new SaleWithdrawalDo();
        withdrawalDo.setSaleId(saleId);
        Date currentDate = new Date();
        withdrawalDo.setSubmitDateEnd(currentDate);
        withdrawalDo.setSubmitDateStart(currentDate);
        withdrawalDo.setStatusCode(SaleWithdrawalConst.StatusCode.NORMAL.getCode());
        Integer usedTimes = withdrawalService.countAmountByDo(withdrawalDo);
        return new ApiWithdrawalCurrentDayCountRes(DAY_WITHDRAWAL_LIMIT_AMOUNT, usedTimes, DAY_WITHDRAWAL_LIMIT_AMOUNT - usedTimes);
    }

    @Override
    public ApiWithdrawalDetailRes getById(Long id) {
        SaleWithdrawalPo withdrawalPo = withdrawalExtendService.getPoByIdNotNull(id);
        return BeanUtil.toBean(withdrawalPo, ApiWithdrawalDetailRes.class);
    }

    @Override
    public PageInfo<ApiWithdrawalPagingRes> paging(ApiWithdrawalPagingReq req) {
        Long saleId = ApiSaleSessionHolder.getSaleId();
        req.setSaleId(saleId);
        List<SaleWithdrawalPo> withdrawalPoList = withdrawalService.listPoByDo(req);
        return PageInfoUtils.toPageInfo(withdrawalPoList, ApiWithdrawalPagingRes.class);
    }
}
